package com.zs.demo.shiro;



import com.zs.demo.common.exception.RestException;
import com.zs.demo.shiro.jwt.JwtUtil;
import com.zs.demo.pojo.entity.system.SysUser;
import com.zs.demo.service.system.SysUserService;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/* @Desc: 充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说，当对用户执行认证（登录）和授权（访问控制）验证时，Shiro会从应用配置的Realm中查找用户及其权限信息
 * @author:zhengs  
 * @Time: 2018/11/22 16:22
 * @Copyright: © zhengs 版权所有  
 * @Warning: 本内容仅限于本公司内部传阅,禁止外泄或用于其它商业目的  
 */
@Slf4j
public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private SysUserService userService;

    @Autowired
    private CacheManager cacheManager;

    /* @Desc:获取用户角色权限+用户权限
     * @author:zhengs  
     * @Time: 2018/11/22 16:31
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        MyToken myToken = new MyToken();
        BeanUtils.copyProperties(principalCollection.getPrimaryPrincipal(), myToken);
        if(myToken.getUsername()!=null){
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            // 获取用户
            SysUser findUser = userService.findUserByName(myToken.getUsername(),true);
            if(findUser!=null){
                if(findUser.getRoles()!=null){
                    findUser.getRoles().forEach(role->{
                        //获取用户角色
                        info.addRole(role.getName());
                        if(role.getResources()!=null){
                            role.getResources().forEach(v->{
                                if(!"".equals(v.getPermission().trim())){
                                    //获取用户权限
                                    info.addStringPermission(v.getPermission());
                                }
                            });
                        }
                    });
                }
                return info;
            }
        }

        throw new DisabledAccountException("用户失效，请重新登录！");
    }

    /* @Desc:验证账号和密码
     * @author:zhengs
     * @Time: 2018/11/22 16:36
     * @param authenticationToken
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        MyToken token  = (MyToken) authenticationToken;
        SysUser user;
        String username = token.getUsername()!=null ? token.getUsername() : JwtUtil.getUsername(token.getToken());
        try {
            user = userService.selectOne(new EntityWrapper<SysUser>()
                    .eq("username",username)
                    .setSqlSelect("id,username,status,password"));
        }catch (RestException e){
            throw new DisabledAccountException(e.getMsg());
        }
        if(user==null){
            throw new DisabledAccountException("用户不存在！");
        }
        if(!"1".equals(user.getStatus())){
            throw new DisabledAccountException("用户账户已锁定，暂无法登陆！");
        }
        if(token.getUsername()==null){
            token.setUsername(user.getUsername());
        }
        if(token.getToken()==null){
            String sign = JwtUtil.createToken(user.getId(), user.getUsername(), user.getPassword());
            token.setToken(sign);
        }
        token.setUid(user.getId());
        return new SimpleAuthenticationInfo(token,user.getPassword(),user.getId());
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof MyToken;
    }

    /* @Desc: 清理单个用户的缓存
     * @author:zhengs
     * @Time: 2018/11/22 16:51
     * @param uid
     * @param author
     * @param out
     * @return
     */
    public void clearAuthByUserId(String uid,Boolean author, Boolean out){
        Cache<Object, Object> cache = cacheManager.getCache("authorizationCache");
        cache.remove(uid);
    }
    
    /* @Desc:清理多个用户的缓存
     * @author:zhengs  
     * @Time: 2018/11/22 16:49
     * @param userList
     * @param author
     * @param out
     * @return
     */
    public void clearAuthByUserIdCollection(List<String> userList,Boolean author, Boolean out){
        Cache<Object, Object> cache = cacheManager.getCache("authorizationCache");
        userList.forEach(cache::remove);
    }
}